home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume7 / getoptprog < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  8.0 KB

  1. Subject:  v07i011:  Getopt program for scripts
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Rich $alz (mirror!rs)
  6. Mod.sources: Volume 7, Issue 11
  7. Archive-name: getoptprog
  8.  
  9. #!/bin/sh
  10. # This is a shell archive.  Remove anything before this line,
  11. # then unpack it by saving it in a file and typing "sh file".
  12. # Wrapped by mirror!rs on Thu Aug 28 12:55:41 EDT 1986
  13.  
  14. # Exit status; set to 1 on "wc" errors or if would overwrite.
  15. STATUS=0
  16. # Contents:  README Makefile getopt.1 getopt.c
  17.  
  18. echo x - README
  19. if test -f README ; then
  20.     echo README exists, putting output in $$README
  21.     OUT=$$README
  22.     STATUS=1
  23. else
  24.     OUT=README
  25. fi
  26. sed 's/^XX//' > $OUT <<'@//E*O*F README//'
  27. XXThis quick throw-off is a public-domain implementation of the USG
  28. XXgetopt program.  Not to be confused with the library routine, this
  29. XXprogram helps scripts parse their options/flags/arguments.
  30.  
  31. XXAfter unpacking, tweak the Makefile as appropriate and run make.  Copy
  32. XXthe examples from the manpage into separate files as verify that they
  33. XXwork ok.  Do a "make install".  For your final examination, convert
  34. XXlint to use this program.  I write more Makefiles for mod.sources
  35. XXsubmissions than I care to, and sometimes I get tired of it; I
  36. XXapologize for the terseness of the one here.
  37.  
  38. XXIf you don't have getopt(3) in your C run-time library, snip it off
  39. XXthe tail of the source file, and add it, or make it easily, publicly,
  40. XXavailable in some other way.
  41. XX    /Rich $alz
  42. @//E*O*F README//
  43. chmod u=rw,g=rw,o=rw $OUT
  44.  
  45. echo x - Makefile
  46. if test -f Makefile ; then
  47.     echo Makefile exists, putting output in $$Makefile
  48.     OUT=$$Makefile
  49.     STATUS=1
  50. else
  51.     OUT=Makefile
  52. fi
  53. sed 's/^XX//' > $OUT <<'@//E*O*F Makefile//'
  54. XX# Pick one
  55. XXCFLAGS    = -O -DINDEX=index
  56. XX#CFLAGS    = -O -DINDEX=strchr
  57. XX# Pick one
  58. XXM    = /usr/man/man1/getopt.1
  59. XX#M    = /usr/man/u_man/man1/getopt.1#  Is this path right?
  60. XX# Where executable ends up; don't forget the trailing /
  61. XXD    = /bin/
  62.  
  63. XXgetopt:        getopt.c
  64. XX    $(CC) $(CFLAGS) -o getopt getopt.c
  65. XXinstall:    getopt
  66. XX    cp getopt $Dgetopt
  67. XX    strip $Dgetopt
  68. XX    cp getopt.1 $M
  69. @//E*O*F Makefile//
  70. chmod u=rw,g=rw,o=rw $OUT
  71.  
  72. echo x - getopt.1
  73. if test -f getopt.1 ; then
  74.     echo getopt.1 exists, putting output in $$getopt.1
  75.     OUT=$$getopt.1
  76.     STATUS=1
  77. else
  78.     OUT=getopt.1
  79. fi
  80. sed 's/^XX//' > $OUT <<'@//E*O*F getopt.1//'
  81. XX.TH GETOPT 1 LOCAL
  82. XX.SH NAME
  83. XXgetopt \- format flags for shell scripts
  84. XX.SH SYNOPSIS
  85. XX.B getopt
  86. XXflag_spec argument ...
  87. XX.SH DESCRIPTION
  88. XX.I Getopt
  89. XXis a program intended to be called by scripts to ``canonicalize'' their
  90. XXarguments before processing them, just as the
  91. XX.IR getopt (3)
  92. XXroutine does for C programs.
  93. XX(This need for scripts is usually most noticeable in the way
  94. XX.IR lint (1)
  95. XXhandles the
  96. XX.B \-n
  97. XXflag.)
  98. XX.PP
  99. XXThe following two examples provide the initial parsing for a script
  100. XXwhich takes two flags,
  101. XX.B \-a
  102. XXand
  103. XX.BR \-b ,
  104. XXthe second of which takes an argument.
  105. XX.RS
  106. XX.ta +4n +4n +4n +4n
  107. XX.nf
  108. XX# For /bin/csh...
  109. XXset argv = (`getopt "ab:" $*`)
  110. XXif ( $status ) then
  111. XX    echo "Read the documentation and try again." >/dev/tty
  112. XX    exit 1
  113. XXendif
  114. XXset Aflag=0
  115. XXset Name=NONE
  116. XXwhile "$1" != "--"
  117. XX    switch ("$1")
  118. XX        case '-a':
  119. XX            set Aflag=1
  120. XX            breaksw
  121. XX        case '-b':
  122. XX            shift
  123. XX            set Name=$1
  124. XX            breaksw
  125. XX    endsw
  126. XX    shift
  127. XXend
  128. XXshift
  129. XXecho Aflag=$Aflag / Name=$Name / Remaining args are $*
  130.  
  131. XX# For /bin/sh...
  132. XXset -- `getopt "d:s" $@`
  133. XXif test $? != 0 ; then
  134. XX    echo "Read the documentation and try again."
  135. XX    exit 1
  136. XXfi
  137. XXAflag=0
  138. XXName=NONE
  139. XXfor f
  140. XXdo
  141. XX    case "$f" in
  142. XX        -a)    Aflag=1
  143. XX            ;;
  144. XX        -b)    shift
  145. XX            Name=$2
  146. XX            ;;
  147. XX        --)    break
  148. XX            ;;
  149. XX    esac
  150. XX    shift
  151. XXdone
  152. XXshift
  153. XXecho Aflag=$Aflag / Name=$Name / Remaining args are $*
  154. XX.fi
  155. XX.RE
  156. XX.SH DIAGNOSTICS
  157. XXThe program burps the standard
  158. XX.IR getopt (3)
  159. XXdiagnostics to standard error, and exits with a non-zero status if an
  160. XXerror occurs.
  161. XXIt is arguable wrong that the diagnostics imply that the program
  162. XXis named ``getopt'' rather than the real name of the script.
  163. XXIt is undeniably AT&T\-compatible to do this, however.
  164. XX.SH "SEE ALSO"
  165. XXcsh(1), sh(1), getopt(3)
  166. XX.SH AUTHOR
  167. XX.nf
  168. XXRich $alz
  169. XXMirror Systems
  170. XX(mirror!rs, rs@mirror.TMC.COM)
  171. @//E*O*F getopt.1//
  172. chmod u=rw,g=rw,o=rw $OUT
  173.  
  174. echo x - getopt.c
  175. if test -f getopt.c ; then
  176.     echo getopt.c exists, putting output in $$getopt.c
  177.     OUT=$$getopt.c
  178.     STATUS=1
  179. else
  180.     OUT=getopt.c
  181. fi
  182. sed 's/^XX//' > $OUT <<'@//E*O*F getopt.c//'
  183. XX/*
  184. XX**  GETOPT PROGRAM AND LIBRARY ROUTINE
  185. XX**
  186. XX**  I wrote main() and AT&T wrote getopt() and we both put our efforts into
  187. XX**  the public domain via mod.sources.
  188. XX**    Rich $alz
  189. XX**    Mirror Systems
  190. XX**    (mirror!rs, rs@mirror.TMC.COM)
  191. XX**    August 10, 1986
  192. XX*/
  193.  
  194. XX#include <stdio.h>
  195.  
  196.  
  197. XX#ifndef INDEX
  198. XX#define INDEX index
  199. XX#endif
  200.  
  201.  
  202. XXextern char    *INDEX();
  203. XXextern int     optind;
  204. XXextern char    *optarg;
  205.  
  206.  
  207. XXmain(ac, av)
  208. XX    register int     ac;
  209. XX    register char     *av[];
  210. XX{
  211. XX    register char     *flags;
  212. XX    register int     c;
  213.  
  214. XX    /* Check usage. */
  215. XX    if (ac < 2) {
  216. XX    fprintf(stderr, "usage: %s flag-specification arg-list\n", av[0]);
  217. XX    exit(2);
  218. XX    }
  219.  
  220. XX    /* Play games; remember the flags (first argument), then splice
  221. XX       them out so it looks like a "standard" command vector. */
  222. XX    flags = av[1];
  223. XX    av[1] = av[0];
  224. XX    av++;
  225. XX    ac--;
  226.  
  227. XX    /* Print flags. */
  228. XX    while ((c = getopt(ac, av, flags)) != EOF) {
  229. XX    if (c == '?')
  230. XX        exit(1);
  231. XX    /* We assume that shells collapse multiple spaces in `` expansion. */
  232. XX    printf("-%c %s ", c, INDEX(flags, c)[1] == ':' ? optarg : "");
  233. XX    }
  234.  
  235. XX    /* End of flags; print rest of options. */
  236. XX    printf("-- ");
  237. XX    for (av += optind; *av; av++)
  238. XX    printf("%s ", *av);
  239. XX    exit(0);
  240. XX}
  241. XX
  242. XX/*
  243. XX**  This is the public-domain AT&T getopt(3) code.  I added the
  244. XX**  #ifndef stuff because I include <stdio.h> for the program;
  245. XX**  getopt, per se, doesn't need it.  I also added the INDEX/index
  246. XX**  hack (the original used strchr, of course).  And, note that
  247. XX**  technically the casts in the write(2) calls shouldn't be there.
  248. XX*/
  249.  
  250. XX#ifndef NULL
  251. XX#define NULL    0
  252. XX#endif
  253. XX#ifndef EOF
  254. XX#define EOF    (-1)
  255. XX#endif
  256. XX#ifndef INDEX
  257. XX#define INDEX index
  258. XX#endif
  259.  
  260.  
  261. XX#define ERR(s, c)    if(opterr){\
  262. XX    extern int strlen(), write();\
  263. XX    char errbuf[2];\
  264. XX    errbuf[0] = c; errbuf[1] = '\n';\
  265. XX    (void) write(2, argv[0], (unsigned)strlen(argv[0]));\
  266. XX    (void) write(2, s, (unsigned)strlen(s));\
  267. XX    (void) write(2, errbuf, 2);}
  268.  
  269. XXextern int strcmp();
  270. XXextern char *INDEX();
  271.  
  272. XXint    opterr = 1;
  273. XXint    optind = 1;
  274. XXint    optopt;
  275. XXchar    *optarg;
  276.  
  277. XXint
  278. XXgetopt(argc, argv, opts)
  279. XXint    argc;
  280. XXchar    **argv, *opts;
  281. XX{
  282. XX    static int sp = 1;
  283. XX    register int c;
  284. XX    register char *cp;
  285.  
  286. XX    if(sp == 1)
  287. XX        if(optind >= argc ||
  288. XX           argv[optind][0] != '-' || argv[optind][1] == '\0')
  289. XX            return(EOF);
  290. XX        else if(strcmp(argv[optind], "--") == NULL) {
  291. XX            optind++;
  292. XX            return(EOF);
  293. XX        }
  294. XX    optopt = c = argv[optind][sp];
  295. XX    if(c == ':' || (cp=INDEX(opts, c)) == NULL) {
  296. XX        ERR(": illegal option -- ", c);
  297. XX        if(argv[optind][++sp] == '\0') {
  298. XX            optind++;
  299. XX            sp = 1;
  300. XX        }
  301. XX        return('?');
  302. XX    }
  303. XX    if(*++cp == ':') {
  304. XX        if(argv[optind][sp+1] != '\0')
  305. XX            optarg = &argv[optind++][sp+1];
  306. XX        else if(++optind >= argc) {
  307. XX            ERR(": option requires an argument -- ", c);
  308. XX            sp = 1;
  309. XX            return('?');
  310. XX        } else
  311. XX            optarg = argv[optind++];
  312. XX        sp = 1;
  313. XX    } else {
  314. XX        if(argv[optind][++sp] == '\0') {
  315. XX            sp = 1;
  316. XX            optind++;
  317. XX        }
  318. XX        optarg = NULL;
  319. XX    }
  320. XX    return(c);
  321. XX}
  322. @//E*O*F getopt.c//
  323. chmod u=rw,g=rw,o=rw $OUT
  324.  
  325. echo Inspecting for damage in transit...
  326. temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
  327. trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
  328. cat > $temp <<\!!!
  329.       15     127     756 README
  330.       15      54     348 Makefile
  331.       90     292    1707 getopt.1
  332.      139     436    2832 getopt.c
  333.      259     909    5643 total
  334. !!!
  335. wc  README Makefile getopt.1 getopt.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
  336. if test -s $dtemp ; then
  337.     echo "Ouch [diff of wc output]:"
  338.     cat $dtemp
  339.     STATUS=1
  340. elif test $STATUS = 0 ; then
  341.     echo "No problems found."
  342. else
  343.     echo "WARNING -- PROBLEMS WERE FOUND..."
  344. fi
  345. exit $STATUS
  346.